#include "lcd_drv.h"
#include "adc_drv.h"
#include "temp_drv.h"

BSP_Lcd_t bsp_lcd;

/* LCD段码屏数据缓存 */
uint8_t array_RAM[16] = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

/* 数码管数据表1 */
const uint8_t array_num1[10] = {
    0xAF, 0xA0, 0xCB, 0xE9, 0xE4, // 0, 1, 2, 3, 4
    0x6D, 0x6F, 0xA8, 0xEF, 0xED  // 5, 6, 7, 8, 9
};

/* 数码管数据表2 */
const uint8_t array_num2[10] = {
    0x5F, 0x06, 0x6B, 0x2F, 0x36, // 0, 1, 2, 3, 4
    0x3D, 0x7D, 0x07, 0x7F, 0x3F  // 5, 6, 7, 8, 9
};

static void GpioInit(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    // GPIOA时钟使能
    RCC_AHBPeriphClk_Enable(LCD_CLK, ENABLE);

    // PA00 -- LCD_LEDCtrl
    GPIO_InitStructure.Pins = LCD_LED_PIN;
    GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStructure.IT = GPIO_IT_NONE;
    GPIO_Init(LCD_PORT, &GPIO_InitStructure);

    // PA01 -- LCD_DATA 数据总线
    GPIO_InitStructure.Pins = LCD_DATA_PIN;
    GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStructure.IT = GPIO_IT_NONE;
    GPIO_Init(LCD_PORT, &GPIO_InitStructure);

    // PA04 -- LCD_CS 片选信号
    GPIO_InitStructure.Pins = LCD_CS_PIN;
    GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStructure.IT = GPIO_IT_NONE;
    GPIO_Init(LCD_PORT, &GPIO_InitStructure);

    // PA06 -- LCD_WR 写时钟线
    GPIO_InitStructure.Pins = LCD_WR_PIN;
    GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStructure.IT = GPIO_IT_NONE;
    GPIO_Init(LCD_PORT, &GPIO_InitStructure);
}

/**
 * @brief 写一位数据到HT1621
 * @param data 数据
 * @param num 个数
 */
static void WriteBitToHT1621(uint8_t data, uint8_t num)
{
    for (uint8_t i = 0; i < num; i++)
    {
        LCD_WR_RESET(); // WR置低

        if (((data & 0x80) >> 7) == 1) // 如果当前bit为1，DATA置高
        {
            LCD_DATA_SET();
        }
        else if (((data & 0x80) >> 7) == 0) // 如果当前bit为0，DATA置低
        {
            LCD_DATA_RESET();
        }
        LCD_WR_SET(); // WR置高
        data <<= 1;   // 移位
    }
}

/**
 * @brief 发送命令到HT1621
 * @param cmdVal 命令
 */
void WriteCmdToHT1621(uint8_t cmdVal)
{
    LCD_CS_RESET(); // CS置低
    WriteBitToHT1621(WRITE_CMD_CODE, 3);
    WriteBitToHT1621(cmdVal, 8);
    WriteBitToHT1621(0, 1);
    LCD_CS_SET(); // CS置高
}

/**
 * @brief 发送数据到HT1621
 * @param addr 地址
 * @param dataVal 数据
 */
void WriteDataToHT1621(uint8_t addr, uint8_t dataVal)
{
    LCD_CS_RESET(); // CS置低
    WriteBitToHT1621(WRITE_DATA_CODE, 3);
    WriteBitToHT1621(addr << 2, 6);
    WriteBitToHT1621(dataVal << 4, 4);
    LCD_CS_SET(); // CS置高
}

/**
 * @brief 发送N个数据到HT1621
 * @param addr 地址
 * @param dataVal 数据
 * @param cnt 数据总数
 */
void WriteNDataToHT1621(uint8_t addr, uint8_t *dataVal, uint8_t cnt)
{
    LCD_CS_RESET(); // CS置低
    WriteBitToHT1621(WRITE_DATA_CODE, 3);
    WriteBitToHT1621(addr << 2, 6);
    for (uint8_t i = 0; i < cnt; i++)
    {
        WriteBitToHT1621(*dataVal++, 8);
    }
    LCD_CS_SET(); // CS置高
}

static void HT1621Init(void)
{
    LCD_CS_SET();
    LCD_WR_SET();
    LCD_DATA_SET();
    WriteCmdToHT1621(HT1621_LCD_OFF);
    WriteCmdToHT1621(HT1621_SYS_EN);
    WriteCmdToHT1621(HT1621_RC256);
    WriteCmdToHT1621(HT1621_BIAS);
    WriteCmdToHT1621(HT1621_LCD_ON);
}

/**
 * @brief LCD硬件初始化
 * @param
 */
void LcdDrvInit(void)
{
    GpioInit();
    HT1621Init();
    LcdClearAll();
}

/**
 * @brief 将缓存区的数据写入HT1621
 * @param
 */
void LcdScan(void)
{
    WriteNDataToHT1621(0, array_RAM, 16);
}

/**
 * @brief LCD清屏
 * @param
 */
void LcdClearAll(void)
{
    for (uint8_t i = 0; i < 4; i++)
    {
        array_RAM[i] = 0x00;
        array_RAM[i + 4] = 0x00;
        array_RAM[i + 8] = 0x00;
        array_RAM[i + 12] = 0x00;
    }
}

/**
 * @brief PV电压显示
 * @param
 */
void PVVoltDisplay(void)
{
    bsp_lcd.PV_V[0] = (app_queue_adc.PV / 10000) % 10;
    bsp_lcd.PV_V[1] = (app_queue_adc.PV / 1000) % 10;
    bsp_lcd.PV_V[2] = (app_queue_adc.PV / 100) % 10;

    /* 显示PV BATT LOAD PV_V */
    array_RAM[12] = (array_RAM[12] & ~0x0E) | 0x0C; // 1100 T1 T3 T4 T5

    array_RAM[15] = (array_RAM[15] & ~0xEF) | array_num1[bsp_lcd.PV_V[0]]; // 1B 1G 1C T18 1A 1F 1E 1D
    array_RAM[14] = (array_RAM[14] & ~0xEF) | array_num1[bsp_lcd.PV_V[1]]; // 2B 2G 2C T2 2A 2F 2E 2D
    array_RAM[14] = (array_RAM[14] & ~0x10) | 0x10;                        // 小数点 T2
    array_RAM[13] = (array_RAM[13] & ~0xEF) | array_num1[bsp_lcd.PV_V[2]]; // 3B 3G 3C T16 3A 3F 3E 3D
}

/**
 * @brief PV电流显示
 * @param
 */
void PVCurrDisplay(void)
{
    bsp_lcd.PV_A[0] = (app_queue_adc.PV_A / 10000) % 10;
    bsp_lcd.PV_A[1] = (app_queue_adc.PV_A / 1000) % 10;
    bsp_lcd.PV_A[2] = (app_queue_adc.PV_A / 100) % 10;

    /* 显示PV BATT LOAD PV_A */
    array_RAM[12] = (array_RAM[12] & ~0x0E) | 0x0A; // 1010 T1 T3 T4 T5

    array_RAM[15] = (array_RAM[15] & ~0xEF) | array_num1[bsp_lcd.PV_A[0]]; // 1B 1G 1C T18 1A 1F 1E 1D
    array_RAM[14] = (array_RAM[14] & ~0xEF) | array_num1[bsp_lcd.PV_A[1]]; // 2B 2G 2C T2 2A 2F 2E 2D
    array_RAM[14] = (array_RAM[14] & ~0x10) | 0x10;                        // 小数点 T2
    array_RAM[13] = (array_RAM[13] & ~0xEF) | array_num1[bsp_lcd.PV_A[2]]; // 3B 3G 3C T16 3A 3F 3E 3D
}

/**
 * @brief 电池电压显示
 * @param
 */
void BATVoltDisplay(void)
{
    bsp_lcd.BAT_V[0] = (app_queue_adc.BAT / 10000) % 10;
    bsp_lcd.BAT_V[1] = (app_queue_adc.BAT / 1000) % 10;
    bsp_lcd.BAT_V[2] = (app_queue_adc.BAT / 100) % 10;

    /* 显示BAT_V */
    array_RAM[9] = (array_RAM[9] & ~0xC0) | 0x80; // 1000 T8 T9 T10 T15

    array_RAM[12] = (array_RAM[12] & ~0xF0) | (array_num1[bsp_lcd.BAT_V[0]] << 4);                                       // 4A 4F 4E 4D T1 T3 T4 T5
    array_RAM[11] = (array_RAM[11] & ~0xFE) | (array_num1[bsp_lcd.BAT_V[1]] << 4) | (array_num1[bsp_lcd.BAT_V[0]] >> 4); // 5A 5F 5E 5D 4B 4G 4C T19
    array_RAM[10] = (array_RAM[10] & ~0xFE) | (array_num1[bsp_lcd.BAT_V[2]] << 4) | (array_num1[bsp_lcd.BAT_V[1]] >> 4); // 6A 6F 6E 6D 5B 5G 5C T7
    array_RAM[10] = (array_RAM[10] & ~0x01) | 0x01;                                                                      // T7 小数点
    array_RAM[9] = (array_RAM[9] & ~0x0E) | (array_num1[bsp_lcd.BAT_V[2]] >> 4);                                         // T8 T9 T10 T15 6B 6G 6C T24
}

/**
 * @brief 电池电流显示
 * @param
 */
void BATCurrDisplay(void)
{
    bsp_lcd.BAT_A[0] = (app_queue_adc.BAT_A / 10000) % 10;
    bsp_lcd.BAT_A[1] = (app_queue_adc.BAT_A / 1000) % 10;
    bsp_lcd.BAT_A[2] = (app_queue_adc.BAT_A / 100) % 10;

    /* 显示BAT_A */
    array_RAM[9] = (array_RAM[9] & ~0xC0) | 0x40; // 0100 T8 T9 T10 T15

    array_RAM[12] = (array_RAM[12] & ~0xF0) | (array_num1[bsp_lcd.BAT_A[0]] << 4);                                       // 4A 4F 4E 4D T1 T3 T4 T5
    array_RAM[11] = (array_RAM[11] & ~0xFE) | (array_num1[bsp_lcd.BAT_A[1]] << 4) | (array_num1[bsp_lcd.BAT_A[0]] >> 4); // 5A 5F 5E 5D 4B 4G 4C T19
    array_RAM[10] = (array_RAM[10] & ~0xFE) | (array_num1[bsp_lcd.BAT_A[2]] << 4) | (array_num1[bsp_lcd.BAT_A[1]] >> 4); // 6A 6F 6E 6D 5B 5G 5C T7
    array_RAM[10] = (array_RAM[10] & ~0x01) | 0x01;                                                                      // T7 小数点
    array_RAM[9] = (array_RAM[9] & ~0x0E) | (array_num1[bsp_lcd.BAT_A[2]] >> 4);                                         // T8 T9 T10 T15 6B 6G 6C T24
}

/**
 * @brief 负载电压显示
 * @param
 */
void LOADVoltDisplay(void)
{
    bsp_lcd.BAT_V[0] = (app_queue_adc.BAT / 10000) % 10;
    bsp_lcd.BAT_V[1] = (app_queue_adc.BAT / 1000) % 10;
    bsp_lcd.BAT_V[2] = (app_queue_adc.BAT / 100) % 10;

    /* 显示LOAD_V */
    array_RAM[6] = (array_RAM[6] & ~0x10) | 0x10; // 9B 9G 9C T13 9A 9F 9E 9D
    array_RAM[8] = (array_RAM[8] & ~0x10) | 0x00; // 7B 7G 7C T14 7A 7F 7E 7D

    array_RAM[8] = (array_RAM[8] & ~0xEF) | array_num1[bsp_lcd.BAT_V[0]]; // 7B 7G 7C T14 7A 7F 7E 7D
    array_RAM[7] = (array_RAM[7] & ~0xEF) | array_num1[bsp_lcd.BAT_V[1]]; // 8B 8G 8C T12 8A 8F 8E 8D
    array_RAM[7] = (array_RAM[7] & ~0x10) | 0x10;                         // T12 小数点
    array_RAM[6] = (array_RAM[6] & ~0xEF) | array_num1[bsp_lcd.BAT_V[2]]; // 9B 9G 9C T13 9A 9F 9E 9D
}

/**
 * @brief 负载电流显示
 * @param
 */
void LOADCurrDisplay(void)
{
    bsp_lcd.BAT_A[0] = (app_queue_adc.BAT_A / 10000) % 10;
    bsp_lcd.BAT_A[1] = (app_queue_adc.BAT_A / 1000) % 10;
    bsp_lcd.BAT_A[2] = (app_queue_adc.BAT_A / 100) % 10;

    /* 显示LOAD_A */
    array_RAM[6] = (array_RAM[6] & ~0x10) | 0x00; // 9B 9G 9C T13 9A 9F 9E 9D
    array_RAM[8] = (array_RAM[8] & ~0x10) | 0x10; // 7B 7G 7C T14 7A 7F 7E 7D

    array_RAM[8] = (array_RAM[8] & ~0xEF) | array_num1[bsp_lcd.BAT_A[0]]; // 7B 7G 7C T14 7A 7F 7E 7D
    array_RAM[7] = (array_RAM[7] & ~0xEF) | array_num1[bsp_lcd.BAT_A[1]]; // 8B 8G 8C T12 8A 8F 8E 8D
    array_RAM[7] = (array_RAM[7] & ~0x10) | 0x10;                         // T12 小数点
    array_RAM[6] = (array_RAM[6] & ~0xEF) | array_num1[bsp_lcd.BAT_A[2]]; // 9B 9G 9C T13 9A 9F 9E 9D
}

/**
 * @brief 温度显示
 * @param
 */
void TempDisplay(void)
{
    bsp_lcd.Temp[0] = (bsp_temp.Temp / 100) % 10;
    bsp_lcd.Temp[1] = (bsp_temp.Temp / 10) % 10;
    bsp_lcd.Temp[2] = bsp_temp.Temp % 10;

    /* 显示℃ 电池图标 */
    array_RAM[4] = array_RAM[4] | 0x30; // 0011 T31 T22 T21 T20

    array_RAM[1] = (array_RAM[1] & ~0x7F) | array_num2[bsp_lcd.Temp[0]]; // T29 10E 10G 10F 10D 10C 10B 10A
    array_RAM[2] = (array_RAM[2] & ~0x7F) | array_num2[bsp_lcd.Temp[1]]; // T30 11E 11G 11F 11D 11C 11B 11A
    array_RAM[3] = (array_RAM[3] & ~0x7F) | array_num2[bsp_lcd.Temp[2]]; // T23 12E 12G 12F 12D 12C 12B 12A
}

/**
 * @brief LCD显示测试
 * @param
 */
void LcdTest(void)
{
    PVVoltDisplay();
    BATVoltDisplay();
    LOADVoltDisplay();
    TempDisplay();
    // WriteNDataToHT1621(0, array_RAM, 16);
}
